home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / animutil / fastgfx / fg303b / manuals.arj / USER11.DOC < prev    next >
Encoding:
Text File  |  1993-10-02  |  34.6 KB  |  794 lines

  1. Chapter 11
  2.  
  3.  
  4.  
  5.  
  6.  
  7. Block Transfer Routines
  8.  
  9. 222   Fastgraph User's Guide
  10.  
  11.  
  12. Overview
  13.  
  14.      The Fastgraph routines described in this chapter transfer rectangular
  15. blocks between areas of video memory (such routines are sometimes called Blit
  16. or BitBlt routines in other literature).  Block transfers are useful in many
  17. graphics applications, but they are especially important in animation.
  18. Fastgraph provides several types of block transfer routines, each optimized
  19. for its specific function.  This chapter will discuss these routines in
  20. detail.  The information presented here, combined with the video page and
  21. image management techniques described in the previous three chapters, will
  22. provide the tools we need for the animation techniques presented in the next
  23. chapter.
  24.  
  25.  
  26. Full Page Transfer
  27.  
  28.      Fastgraph's simplest block transfer routine is fg_copypage, which we
  29. introduced in Chapter 8.  The fg_copypage routine transfers the entire
  30. contents of one video page to another.  The first argument is the number of
  31. the source video page, and the second argument is the number of the
  32. destination video page.  The pages may be physical, virtual, or logical video
  33. pages.  If both the source and destination pages are logical pages, the pages
  34. must exist in the same type of memory.  For example, you cannot copy a
  35. logical page in extended memory to a logical page in conventional memory.
  36.  
  37.      Example 11-1 illustrates the use of the fg_copypage routine in a 320 by
  38. 200 color graphics mode.  The program displays the word "test" in the middle
  39. of the visual page (page 0) and then uses fg_allocate to create a virtual
  40. video page (page 1).  The virtual page is needed in case the program is
  41. running in a video mode with only one physical page.  Next, the program uses
  42. fg_copypage to transfer the visual page contents to page 1.  After waiting
  43. for a keystroke, the program erases the visual page, waits for another
  44. keystroke, and copies the contents of page 1 back to the visual page.  It
  45. then releases the virtual page and exits.
  46.  
  47.                                 Example 11-1.
  48.  
  49.                 #include <fastgraf.h>
  50.                 #include <stdio.h>
  51.                 #include <stdlib.h>
  52.                 void main(void);
  53.  
  54.                 void main()
  55.                 {
  56.                    int new_mode, old_mode;
  57.  
  58.                    new_mode = fg_bestmode(320,200,2);
  59.                    if (new_mode < 0 || new_mode == 12) {
  60.                       printf("This program requires a 320 ");
  61.                       printf("x 200 color graphics mode.\n");
  62.                       exit(1);
  63.                       }
  64.                    old_mode = fg_getmode();
  65.                    fg_setmode(new_mode);
  66.  
  67.                    fg_setcolor(7);
  68.                                     Chapter 11:  Block Transfer Routines   223
  69.  
  70.  
  71.                    fg_rect(0,319,0,199);
  72.                    fg_setcolor(9);
  73.                    fg_locate(12,18);
  74.                    fg_text("test",4);
  75.                    fg_waitkey();
  76.  
  77.                    fg_allocate(1);
  78.                    fg_copypage(0,1);
  79.                    fg_erase();
  80.                    fg_waitkey();
  81.  
  82.                    fg_copypage(1,0);
  83.                    fg_waitkey();
  84.  
  85.                    fg_freepage(1);
  86.                    fg_setmode(old_mode);
  87.                    fg_reset();
  88.                 }
  89.  
  90.  
  91. Byte Boundaries
  92.  
  93.      Video memory, like standard random-access memory, is divided into units
  94. called bytes.  In text modes, each byte holds either a character or an
  95. attribute.  In graphics modes, each byte of video memory holds one or more
  96. horizontally contiguous pixels.  If two adjacent horizontal pixels are stored
  97. in different bytes, then we say a byte boundary exists between the two
  98. pixels.
  99.  
  100.      The number of pixels per byte depends on the video mode being used, so
  101. the location of the byte boundaries also depends on the video mode.  That is,
  102. a byte boundary in a CGA graphics mode is not necessarily a byte boundary in
  103. a VGA graphics mode.  The following table summarizes the number of pixels per
  104. byte of video memory and the byte boundary sequences for each supported
  105. graphics video mode.  Note that any horizontal coordinate whose value is a
  106. multiple of 8 is always a byte boundary, regardless of the video mode.
  107.  
  108.                   mode     pixels     horizontal coordinates
  109.                  number   per byte    of byte boundaries
  110.  
  111.                     4         4       0, 4,  8, 12, ... , 316
  112.                     5         4       0, 4,  8, 12, ... , 316
  113.                     6         8       0, 8, 16, 24, ... , 632
  114.                     9         2       0, 2,  4,  6, ... , 318
  115.                    11         8       0, 8, 16, 24, ... , 712
  116.                    12         4       0, 4,  8, 12, ... , 316
  117.                    13         8       0, 8, 16, 24, ... , 312
  118.                    14         8       0, 8, 16, 24, ... , 632
  119.                    15         8       0, 8, 16, 24, ... , 632
  120.                    16         8       0, 8, 16, 24, ... , 632
  121.                    17         8       0, 8, 16, 24, ... , 632
  122.                    18         8       0, 8, 16, 24, ... , 632
  123.                    19         1       0, 1,  2,  3, ... , 319
  124.                    20         1       0, 4,  8, 12, ... , 316
  125.                    21         1       0, 4,  8, 12, ... , 316
  126.                    22         1       0, 4,  8, 12, ... , 316
  127. 224   Fastgraph User's Guide
  128.  
  129.                    23         1       0, 4,  8, 12, ... , 316
  130.                    24         1       0, 1,  2,  3, ... , 639
  131.                    25         1       0, 1,  2,  3, ... , 639
  132.                    26         1       0, 1,  2,  3, ... , 799
  133.                    27         1       0, 1,  2,  3, ... , 1023
  134.                    28         8       0, 8, 16, 24, ... , 792
  135.                    29         8       0, 8, 16, 24, ... , 1016
  136.  
  137.      Block transfer routines are often used in animation sequences requiring
  138. high-performance graphics, so these routines must be as efficient as
  139. possible.  To this end, Fastgraph will force their horizontal pixel
  140. coordinates to byte boundaries, which eliminates the need to process any
  141. pixels individually.  Fastgraph accomplishes this by reducing minimum
  142. horizontal coordinates to a byte boundary and extending maximum horizontal
  143. coordinates to the last pixel in a video memory byte.  Note that since we are
  144. talking about pixel coordinates and not character cells, the coordinate
  145. modification only occurs in graphics video modes.  Designing an application
  146. so that block transfers occur on byte boundaries might take additional
  147. planning, but it will be time well spent.
  148.  
  149.      An example might best help explain this important feature.  In the
  150. EGA/VGA/SVGA 16-color graphics modes (modes 13 to 18, 28, and 29),  byte
  151. boundaries occur at every eighth pixel.  Thus, when you use the block
  152. transfer routines in these modes, Fastgraph reduces minimum x coordinates to
  153. the next lower multiple of eight.  Similarly, it extends their maximum x
  154. coordinates to the next higher multiple of eight, less one pixel.  That is,
  155. if a minimum x coordinate is 10 and a maximum x coordinate is 30, Fastgraph
  156. will modify these values to 8 and 31 respectively.  If the x coordinates were
  157. originally 8 and 31, Fastgraph would leave them unchanged.
  158.  
  159.      In the MCGA and SVGA 256-color graphics modes (modes 19 and 24 to 27)
  160. each pixel occupies a separate byte of video memory, so Fastgraph does not
  161. need to modify horizontal coordinates.  However, in the XVGA graphics modes
  162. (modes 20 to 23), some coordinate modification might be needed.  The XVGA
  163. modes store four pixels at each video memory address, one in each of four bit
  164. planes.  The bit plane number for a pixel whose horizontal coordinate is x is
  165. given by the quantity x mod 4.  In XVGA modes, the source and destination
  166. minimum x coordinates must reference pixels in the same bit plane.  Put
  167. another way, the relation
  168.  
  169.                   xmin_source mod 4 = xmin_destination mod 4
  170.  
  171. must be true.  If it isn't, Fastgraph reduces the destination minimum x value
  172. to the same bit plane as the source minimum x value.
  173.  
  174.  
  175. Dual SVGA Banks
  176.  
  177.      Accessing video memory in SVGA graphics modes is controlled through a
  178. banking scheme that maps contiguous 64KB blocks of video memory into a
  179. segmented address space.  In other words, referencing a specific byte in
  180. video memory requires a bank number and an address within that bank.  Some
  181. SVGA chipsets provide separate read and write bank registers, while others
  182. perform both operations through the same bank register.
  183.  
  184.      If a chipset supports separate read and write banks, Fastgraph's block
  185. transfer routines can copy the source region directly to the destination
  186.                                     Chapter 11:  Block Transfer Routines   225
  187.  
  188. region.  However, chipsets that employ a single bank register require that
  189. these routines copy the source region to an intermediate buffer and then copy
  190. the buffer contents to the destination.  This obviously makes a block
  191. transfer operation slower on single-bank chipsets.
  192.  
  193.  
  194. The "Hidden" Video Page
  195.  
  196.      Some of Fastgraph's block transfer routines reference a video page
  197. called the hidden page.  The Fastgraph routine fg_sethpage defines which
  198. video page will be used as the hidden page.  This routine takes as its only
  199. argument an integer value specifying the hidden page number.  If you are
  200. using a virtual video page for the hidden page, you must call the fg_sethpage
  201. routine after allocating that page.  There is also a routine named
  202. fg_gethpage that returns the hidden page number, as specified in the most
  203. recent call to fg_sethpage, as its function value.  The fg_gethpage routine
  204. takes no arguments.
  205.  
  206.  
  207. Saving and Restoring Blocks
  208.  
  209.      The next two block transfer routines we'll discuss are fg_save and
  210. fg_restore.  The fg_save routine transfers a rectangular region from the
  211. active video page (as defined in the most recent call to fg_setpage) to the
  212. same position on the hidden video page (as defined in the most recent call to
  213. fg_sethpage).  The fg_restore routine performs the complementary task -- it
  214. transfers a rectangular region from the hidden page to the active page.  Each
  215. of these routines requires four arguments that define the coordinates of the
  216. block to transfer, in the order minimum x, maximum x, minimum y, and maximum
  217. y.  In text modes, the coordinates are expressed as character space
  218. quantities (rows and columns).  In graphics modes, they are expressed as
  219. screen space values (pixels), with the x coordinates extended to byte
  220. boundaries if required.  There are also world space versions of these
  221. routines named fg_savew and fg_restorew available in graphics modes.
  222.  
  223.      Example 11-2 demonstrates the use of Fastgraph's fg_save, fg_restore,
  224. and fg_sethpage routines in an 80-column text video mode.  After establishing
  225. the video mode (note the calls to fg_testmode specify that two video pages
  226. are needed), the program fills the screen with text and then waits for a
  227. keystroke.  Following this, the program displays a small pop-up window
  228. prompting for another keystroke.  After waiting for the second keystroke, the
  229. program erases the pop-up window by restoring the original screen contents,
  230. and then waits for yet another keystroke before returning to DOS.  We'll
  231. present the program now, and afterward analyze it in detail.
  232.  
  233.                                 Example 11-2.
  234.  
  235.                 #include <fastgraf.h>
  236.                 #include <stdio.h>
  237.                 #include <stdlib.h>
  238.                 void main(void);
  239.  
  240.                 void main()
  241.                 {
  242.                    int row;
  243.                    int old_mode;
  244.                    char string[17];
  245. 226   Fastgraph User's Guide
  246.  
  247.  
  248.  
  249.                    old_mode = fg_getmode();
  250.  
  251.                    if (fg_testmode(3,2))
  252.                       fg_setmode(3);
  253.                    else if (fg_testmode(7,2))
  254.                       fg_setmode(7);
  255.                    else {
  256.                       printf("This program requires\n");
  257.                       printf("an 80-column display.\n");
  258.                       exit(1);
  259.                       }
  260.  
  261.                    fg_cursor(0);
  262.                    fg_setattr(9,7,0);
  263.  
  264.                    for (row = 0; row < 25; row++) {
  265.                       sprintf(string," This is row %2d ",row);
  266.                       fg_locate(row,0);
  267.                       fg_text(string,16);
  268.                       fg_text(string,16);
  269.                       fg_text(string,16);
  270.                       fg_text(string,16);
  271.                       fg_text(string,16);
  272.                       }
  273.                    fg_waitkey();
  274.  
  275.                    fg_allocate(1);
  276.                    fg_sethpage(1);
  277.                    fg_save(32,47,11,13);
  278.                    fg_setcolor(1);
  279.                    fg_rect(32,47,11,13);
  280.                    fg_setattr(15,1,0);
  281.                    fg_locate(12,33);
  282.                    fg_text("Press any key.",14);
  283.                    fg_waitkey();
  284.  
  285.                    fg_restore(32,47,11,13);
  286.                    fg_waitkey();
  287.  
  288.                    fg_freepage(1);
  289.                    fg_setmode(old_mode);
  290.                    fg_reset();
  291.                 }
  292.  
  293.      Example 11-2 first establishes the video mode and uses the fg_cursor
  294. routine to make the BIOS cursor invisible.  It then executes a for loop that
  295. fills each row of the screen with the phrase "This is row n", where n is the
  296. row number (between 0 and 24).  Next, the program uses the fg_allocate
  297. routine to create video page 1 as a virtual video page.  This is needed in
  298. case the program is running in mode 7, which has only one true page (if the
  299. program is running in mode 3, the call to fg_allocate has no effect).  The
  300. program then makes page 1 the hidden page by calling the fg_sethpage routine.
  301.  
  302.      After setting up the hidden video page, but before displaying the pop-up
  303. window, example 11-2 uses the fg_save routine to save the current contents of
  304.                                     Chapter 11:  Block Transfer Routines   227
  305.  
  306. the area that the pop-up window will replace.  The fg_save routine copies
  307. this region to the hidden page.  The program then displays the pop-up window
  308. in the middle of the screen and leaves it there until a key is pressed.
  309. Following this, the program uses the fg_restore routine to replace the pop-up
  310. window with the original contents of that region.  This effectively erases
  311. the pop-up window and restores the original screen.  The program then waits
  312. for another keystroke, after which it releases the virtual page and returns
  313. to DOS.
  314.  
  315.      The next example, 11-3, is similar to example 11-2, but it runs in a 320
  316. by 200 color graphics mode instead of a text mode.  The main differences
  317. between this program and example 11-2 are the use of 40-column text and the
  318. use of screen space coordinates instead of character space coordinates in the
  319. calls to fg_save, fg_restore, and fg_rect.  Note that the call to fg_allocate
  320. creates a virtual page if the program is running in modes 4, 9, or 19.  In
  321. modes 13 and 20, which respectively have four and eight physical pages,
  322. fg_allocate does nothing.
  323.  
  324.                                 Example 11-3.
  325.  
  326.               #include <fastgraf.h>
  327.               #include <stdio.h>
  328.               #include <stdlib.h>
  329.               void main(void);
  330.  
  331.               void main()
  332.               {
  333.                  int row;
  334.                  int new_mode, old_mode;
  335.                  char string[21];
  336.  
  337.                  new_mode = fg_bestmode(320,200,2);
  338.                  if (new_mode < 0 || new_mode == 12) {
  339.                     printf("This program requires a 320 ");
  340.                     printf("x 200 color graphics mode.\n");
  341.                     exit(1);
  342.                     }
  343.                  old_mode = fg_getmode();
  344.                  fg_setmode(new_mode);
  345.  
  346.                  fg_setcolor(7);
  347.                  fg_rect(0,319,0,199);
  348.                  fg_setcolor(9);
  349.  
  350.                  for (row = 0; row < 25; row++) {
  351.                     sprintf(string,"   This is row %2d   ",row);
  352.                     fg_locate(row,0);
  353.                     fg_text(string,20);
  354.                     fg_text(string,20);
  355.                     }
  356.                  fg_waitkey();
  357.  
  358.                  fg_allocate(1);
  359.                  fg_sethpage(1);
  360.                  fg_save(96,223,88,111);
  361.                  fg_setcolor(1);
  362.                  fg_rect(96,223,88,111);
  363. 228   Fastgraph User's Guide
  364.  
  365.  
  366.                  fg_setcolor(15);
  367.                  fg_locate(12,13);
  368.                  fg_text("Press any key.",14);
  369.                  fg_waitkey();
  370.  
  371.                  fg_restore(96,223,88,111);
  372.                  fg_waitkey();
  373.  
  374.                  fg_freepage(1);
  375.                  fg_setmode(old_mode);
  376.                  fg_reset();
  377.               }
  378.  
  379.  
  380.  
  381. A More General Block Transfer Routine
  382.  
  383.      The fg_save and fg_restore routines each copy a rectangular region from
  384. one video page to the same position on another video page.  What if you need
  385. to copy the region to a different position on another video page, or copy it
  386. elsewhere on the same video page?  Fastgraph provides a more general block
  387. transfer routine named fg_transfer.  The fg_transfer routine copies a
  388. rectangular region on any video page to any position on any video page.  Like
  389. fg_save and fg_restore, the fg_transfer routine works in text and graphics
  390. video modes.  In graphics modes, fg_transfer extends its x coordinates to
  391. byte boundaries if necessary.
  392.  
  393.      The fg_transfer routine requires eight integer arguments.  The first
  394. four arguments define the region to copy, in the same order as expected by
  395. fg_save and fg_restore.  The next two arguments define the lower left corner
  396. of the block destination, while the final two arguments respectively specify
  397. the source and destination video page numbers.  In short, fg_transfer copies
  398. the specified region from the source page to the specified position on the
  399. destination page.
  400.  
  401.      Example 11-4 is the same as example 11-2, but it uses fg_transfer rather
  402. than fg_save and fg_restore.  We have arbitrarily chosen to copy the region
  403. overwritten by the pop-up window to the lower left corner of the hidden page
  404. (page 1).  When we copy this region back to the visual page, we copy from the
  405. lower left corner of the hidden page back to the original position on the
  406. visual page (page 0).  This sequence is shown in the following diagram.
  407.  
  408.              (11,32)    (11,47)               (22,0)     (22,15)
  409.                                 first call
  410.                This is row 11   ------------>   This is row 11
  411.                This is row 12                   This is row 12
  412.                This is row 13   <------------   This is row 13
  413.                                   second call
  414.              (13,32)    (13,47)               (24,0)     (24,15)
  415.  
  416.                 visual page (0)                  hidden page (1)
  417.  
  418. To copy one region to a new position and then back to its original position,
  419. note how we make the fifth and sixth arguments in the first call to
  420. fg_transfer the same values as the first and fourth arguments in the second
  421. call.  Similarly, the fifth and sixth arguments in the second call must be
  422.                                     Chapter 11:  Block Transfer Routines   229
  423.  
  424. the same as the first and fourth arguments in the first call.  With all that
  425. out of the way, here is example 11-4.
  426.  
  427.                                 Example 11-4.
  428.  
  429.                 #include <fastgraf.h>
  430.                 #include <stdio.h>
  431.                 #include <stdlib.h>
  432.                 void main(void);
  433.  
  434.                 void main()
  435.                 {
  436.                    int row;
  437.                    int old_mode;
  438.                    char string[17];
  439.  
  440.                    old_mode = fg_getmode();
  441.                    if (fg_testmode(3,2))
  442.                       fg_setmode(3);
  443.                    else if (fg_testmode(7,2))
  444.                       fg_setmode(7);
  445.                    else {
  446.                       printf("This program requires\n");
  447.                       printf("an 80-column display.\n");
  448.                       exit(1);
  449.                       }
  450.  
  451.                    fg_cursor(0);
  452.                    fg_setattr(9,7,0);
  453.  
  454.                    for (row = 0; row < 25; row++) {
  455.                       sprintf(string," This is row %2d ",row);
  456.                       fg_locate(row,0);
  457.                       fg_text(string,16);
  458.                       fg_text(string,16);
  459.                       fg_text(string,16);
  460.                       fg_text(string,16);
  461.                       fg_text(string,16);
  462.                       }
  463.                    fg_waitkey();
  464.  
  465.                    fg_allocate(1);
  466.                    fg_transfer(32,47,11,13,0,24,0,1);
  467.                    fg_setcolor(1);
  468.                    fg_rect(32,47,11,13);
  469.                    fg_setattr(15,1,0);
  470.                    fg_locate(12,33);
  471.                    fg_text("Press any key.",14);
  472.                    fg_waitkey();
  473.  
  474.                    fg_transfer(0,15,22,24,32,13,1,0);
  475.                    fg_fg_waitkey();
  476.  
  477.                    fg_freepage(1);
  478.                    fg_setmode(old_mode);
  479.                    fg_reset();
  480.                 }
  481. 230   Fastgraph User's Guide
  482.  
  483.  
  484.      Example 11-5 illustrates another use of the fg_transfer routine.  This
  485. example is functionally identical to example 10-10, but it uses fg_transfer
  486. instead of fg_getmap and fg_drawmap.  With the fg_transfer routine, we
  487. eliminate the calls to fg_getmap and fg_drawmap, the two calls to fg_move,
  488. and the 32-byte array needed to retrieve the block.  As an added bonus, using
  489. fg_transfer is much faster than the technique of example 10-10, although we
  490. probably won't notice this gain with such a small block.
  491.  
  492.      The block copied in example 11-5 is one row of four characters, so its
  493. width in screen space is 32 pixels and its height is 8 pixels.  Because the
  494. block is in the upper left corner of the screen, the block boundaries are
  495. xmin=0, xmax=31, ymin=0, and ymax=7.  We want to move the block one-half
  496. character cell (4 pixels) to the right and one row (8 pixels) down, so our
  497. destination coordinates are x=4 (xmin+4) and y=15 (ymax+8).  Note how the
  498. program restricts itself to modes 19 and 20 to insure the block copy is not
  499. affected by byte boundaries.  Also, we are copying the block from one
  500. position to another on the visual page, so both the source and destination
  501. pages are 0.
  502.  
  503.                                 Example 11-5.
  504.  
  505.                  #include <fastgraf.h>
  506.                  #include <stdio.h>
  507.                  #include <stdlib.h>
  508.                  void main(void);
  509.  
  510.                  void main()
  511.                  {
  512.                     int old_mode, new_mode;
  513.  
  514.                     new_mode = fg_bestmode(320,200,1);
  515.                     if (new_mode < 19) {
  516.                        printf("This program requires a ");
  517.                        printf("256-color graphics mode.\n");
  518.                        exit(1);
  519.                        }
  520.  
  521.                     old_mode = fg_getmode();
  522.                     fg_setmode(new_mode);
  523.  
  524.                     fg_setcolor(9);
  525.                     fg_text("text",4);
  526.                     fg_waitkey();
  527.  
  528.                     fg_transfer(0,31,0,7,4,15,0,0);
  529.                     fg_waitkey();
  530.  
  531.                     fg_setmode(old_mode);
  532.                     fg_reset();
  533.                  }
  534.  
  535.  
  536.      Example 11-6 shows yet another application of the fg_transfer routine in
  537. a graphics video mode.  The program displays a rectangle in the upper left
  538.                                     Chapter 11:  Block Transfer Routines   231
  539.  
  540.  
  541. quadrant of the screen and then centers the word "quadrant" inside the
  542. rectangle.  After waiting for a keystroke, the program uses fg_transfer to
  543. first copy the upper left quadrant to the upper right quadrant.  It then uses
  544. fg_transfer again to copy the upper half of the screen to the lower half.
  545. The result of this is the screen being filled with what was originally in the
  546. upper left quadrant.
  547.  
  548.                                 Example 11-6.
  549.  
  550.                 #include <fastgraf.h>
  551.                 #include <stdio.h>
  552.                 #include <stdlib.h>
  553.                 void main(void);
  554.  
  555.                 void main()
  556.                 {
  557.                    int new_mode, old_mode;
  558.  
  559.                    new_mode = fg_bestmode(320,200,1);
  560.                    if (new_mode < 0 || new_mode == 12) {
  561.                       printf("This program requires a 320 ");
  562.                       printf("x 200 color graphics mode.\n");
  563.                       exit(1);
  564.                       }
  565.                    old_mode = fg_getmode();
  566.                    fg_setmode(new_mode);
  567.  
  568.                    fg_setcolor(7);
  569.                    fg_rect(0,159,0,99);
  570.                    fg_setcolor(9);
  571.                    fg_locate(6,6);
  572.                    fg_text("quadrant",8);
  573.                    fg_waitkey();
  574.  
  575.                    fg_transfer(0,159,0,99,160, 99,0,0);
  576.                    fg_transfer(0,319,0,99,  0,199,0,0);
  577.                    fg_waitkey();
  578.  
  579.                    fg_setmode(old_mode);
  580.                    fg_reset();
  581.                 }
  582.  
  583.  
  584.  
  585. Blocks with Transparent Colors
  586.  
  587.      The final routines pertaining to block transfer are fg_tcxfer,
  588. fg_tcmask, and fg_tcdefine.  The fg_tcxfer routine is similar to fg_transfer
  589. in that it copies a rectangular region from one position to another, but
  590. fg_tcxfer allows you to treat one or more colors as transparent (the name
  591. fg_tcxfer stands for transparent color transfer).  In other words, any pixel
  592. whose color value is defined to be transparent is not copied to the
  593. destination area.  The fg_tcxfer routine's arguments are the same as for the
  594. fg_transfer routine, but fg_tcxfer has no effect in text video modes.
  595. Because fg_tcxfer must examine the color of individual pixels, it is not
  596. nearly as fast as fg_transfer.
  597. 232   Fastgraph User's Guide
  598.  
  599.  
  600.      You can use either fg_tcmask or fg_tcdefine to define which colors are
  601. considered transparent in subsequent calls to fg_tcxfer.  The fg_tcmask
  602. routine's argument is an integer bit mask (specifically, a 16-bit mask) where
  603. each bit indicates whether or not the color is transparent.  For example, if
  604. bit 0 (the rightmost bit) is set in the mask, then color 0 will be
  605. transparent; if bit 0 is reset, color 0 will not be transparent.  Because the
  606. bit mask size is 16 bits, only the first 16 color values may be defined as
  607. transparent using fg_tcmask.
  608.  
  609.      Example 11-7 illustrates the use of the fg_tcxfer and fg_tcmask
  610. routines.  This program is similar to example 11-6, except the color of the
  611. word "quadrant" (color 9) is defined to be transparent, and fg_tcxfer is used
  612. in place of fg_transfer.  Because color 9 maps to color 1 in the CGA four-
  613. color graphics mode (mode 4), we must define both colors 1 and 9 to be
  614. transparent (remember, fg_tcmask considers actual color values transparent,
  615. not color indices).  The bit mask passed to fg_tcmask thus will be 0000 0010
  616. 0000 0010 binary, or 0202 hex.  This causes the word "quadrant" to appear in
  617. the background color (color 0) instead of color 9 in the upper right, lower
  618. left, and lower right quadrants.
  619.  
  620.                                 Example 11-7.
  621.  
  622.                 #include <fastgraf.h>
  623.                 #include <stdio.h>
  624.                 #include <stdlib.h>
  625.                 void main(void);
  626.  
  627.                 void main()
  628.                 {
  629.                    int new_mode, old_mode;
  630.  
  631.                    new_mode = fg_bestmode(320,200,1);
  632.                    if (new_mode < 0 || new_mode == 12) {
  633.                       printf("This program requires a 320 ");
  634.                       printf("x 200 color graphics mode.\n");
  635.                       exit(1);
  636.                       }
  637.                    old_mode = fg_getmode();
  638.                    fg_setmode(new_mode);
  639.  
  640.                    fg_setcolor(7);
  641.                    fg_rect(0,159,0,99);
  642.                    fg_setcolor(9);
  643.                    fg_locate(6,6);
  644.                    fg_text("quadrant",8);
  645.                    fg_waitkey();
  646.  
  647.                    fg_tcmask(0x0202);
  648.                    fg_tcxfer(0,159,0,99,160, 99,0,0);
  649.                    fg_tcxfer(0,319,0,99,  0,199,0,0);
  650.                    fg_waitkey();
  651.  
  652.                    fg_setmode(old_mode);
  653.                    fg_reset();
  654.                 }
  655.  
  656.                                     Chapter 11:  Block Transfer Routines   233
  657.  
  658.  
  659.      The fg_tcdefine routine expects two integer arguments -- one defining
  660. the color number (between 0 and 255) and another defining the transparency
  661. state associated with that color.  If the state is zero, the specified color
  662. will be opaque (non-transparent).  If it is any other value, the color will
  663. be transparent.  In the previous example, we could use fg_tcdefine instead of
  664. fg_tcmask to make colors 1 and 9 transparent by replacing the call to
  665. fg_tcmask with the following:
  666.  
  667.                               fg_tcdefine(1,1);
  668.                               fg_tcdefine(9,1);
  669.  
  670. If you don't call fg_tcmask or fg_tcdefine, the fg_tcxfer routine considers
  671. no colors transparent.
  672.  
  673.  
  674. Transferring Blocks to and from Conventional Memory
  675.  
  676.      The final two block transfer routines we'll discuss are fg_getblock and
  677. fg_putblock.  The fg_getblock routine transfers a rectangular region from the
  678. active video page to a buffer (you can use fg_imagesiz to determine the
  679. buffer size needed to store the block).  The fg_putblock routine transfers a
  680. block previously retrieved with fg_getblock to the active page.  While these
  681. two routines are faster than fg_getimage and fg_putimage, they are not as
  682. fast as fg_restore, fg_save, and fg_transfer.
  683.  
  684.      Each of these routines requires five arguments.  The first is the
  685. address of the buffer that will receive or that contains the block.  The
  686. remaining four arguments define the position of the block on the active page,
  687. in the order minimum x, maximum x, minimum y, and maximum y.  In text modes,
  688. the coordinates are expressed as character space quantities (rows and
  689. columns).  In graphics modes, they are expressed as screen space values
  690. (pixels), with the x coordinates extended to byte boundaries if required.
  691.  
  692.      Note that both fg_getblock and fg_putblock expect the buffer address to
  693. be passed by far reference except in QuickBASIC.  This means Pascal programs
  694. must use the GetMem procedure to allocate storage for the buffer, as this is
  695. the only way to pass something by far reference in Pascal.  Regardless of
  696. which compiler you're using, the maximum size of a block is 64K bytes.
  697.  
  698.      Example 11-8 is similar to example 11-5 and shows fg_getblock and
  699. fg_putblock in action in a 320 by 200 graphics mode.  The program displays
  700. the word "text" and retrieves it into a 32 by 8 pixel block.  After a
  701. keystroke, it displays the block 8 pixels below and 8 pixels to the right of
  702. its original position.  The size of the buffer was chosen to be 256 bytes to
  703. accommodate the largest size required for a 32 by 8 block (which occurs in
  704. the 256-color graphics modes).  Note also how the source and destination
  705. horizontal block extremes were chosen for byte boundary alignment in case
  706. fg_bestmode selected a 16-color graphics mode.
  707.  
  708.                                 Example 11-8.
  709.  
  710.                 #include <fastgraf.h>
  711.                 #include <stdio.h>
  712.                 #include <stdlib.h>
  713.                 void main(void);
  714.  
  715. 234   Fastgraph User's Guide
  716.  
  717.  
  718.  
  719.                 char far buffer[256];
  720.  
  721.                 void main()
  722.                 {
  723.                    int old_mode, new_mode;
  724.  
  725.                    new_mode = fg_bestmode(320,200,1);
  726.                    if (new_mode < 0 || new_mode == 12) {
  727.                       printf("This program requires a 320 ");
  728.                       printf("x 200 color graphics mode.\n");
  729.                       exit(1);
  730.                       }
  731.  
  732.                    old_mode = fg_getmode();
  733.                    fg_setmode(new_mode);
  734.  
  735.                    fg_setcolor(9);
  736.                    fg_text("text",4);
  737.                    fg_getblock(buffer,0,31,0,7);
  738.                    fg_waitkey();
  739.  
  740.                    fg_putblock(buffer,8,39,8,15);
  741.                    fg_waitkey();
  742.  
  743.                    fg_setmode(old_mode);
  744.                    fg_reset();
  745.                 }
  746.  
  747.  
  748. Summary of Block Transfer Routines
  749.  
  750.      This section summarizes the functional descriptions of the Fastgraph
  751. routines presented in this chapter.  More detailed information about these
  752. routines, including their arguments and return values, may be found in the
  753. Fastgraph Reference Manual.
  754.  
  755.      For all block transfer routines, Fastgraph extends the horizontal pixel
  756. coordinates to a byte boundary when the routines are used in a graphics video
  757. mode.
  758.  
  759.      FG_COPYPAGE transfers the contents of one video page to another.  The
  760. pages may be physical, virtual, or logical video pages.  If both pages are
  761. logical pages, they must exist in the same type of memory.
  762.  
  763.      FG_GETBLOCK retrieves the block (for later display with fg_putblock) at
  764. the specified position on the active video page.  In text modes, the block
  765. extremes are defined in character space; in graphics modes, they are defined
  766. in screen space.
  767.  
  768.      FG_GETHPAGE returns the hidden page number, as defined in the most
  769. recent call to fg_sethpage.
  770.  
  771.      FG_PUTBLOCK displays the block (previously obtained with fg_getblock) at
  772. the specified position on the active video page.  In text modes, the block
  773.                                     Chapter 11:  Block Transfer Routines   235
  774.  
  775.  
  776. extremes are defined in character space; in graphics modes, they are defined
  777. in screen space.
  778.  
  779.      FG_RESTORE copies a block from the hidden video page to the same
  780. position on the active video page.
  781.  
  782.      FG_RESTOREW is the same as fg_restore, but the block extremes are
  783. specified as world space coordinates.
  784.  
  785.      FG_SAVE copies a block from the active video page to the same position
  786. on the hidden video page.
  787.  
  788.      FG_SAVEW is the same as fg_save, but the block extremes are specified as
  789. world space coordinates.
  790.  
  791.      FG_SETHPAGE defines the hidden video page (used by fg_restore,
  792. fg_restorew, fg_save, and fg_savew).
  793.  
  794.      FG_TCDEFINE defines the transparent attribute of a color index for use
  795. with the fg_tcxfer routine.  This routine has no effect when used in a text
  796. video mode.
  797.  
  798.      FG_TCMASK defines which of the first 16 colors the fg_tcxfer routine
  799. will consider transparent.  This routine has no effect when used in a text
  800. video mode.
  801.  
  802.      FG_TCXFER copies a block from any position on any video page to any
  803. position on any video page, excluding any pixels whose color value is
  804. transparent.  This routine has no effect when used in a text video mode.
  805.  
  806.      FG_TRANSFER copies a block from any position on any video page to any
  807. position on any video page.  It is Fastgraph's most general block transfer
  808. routine.
  809. 236   Fastgraph User's Guide
  810.